package cn.tsoft
{
	import cn.tsoft.common.IMonitorToken;
	import cn.tsoft.common.IProgressMonitor;

	import flash.display.DisplayObject;

	public class AbstractResponder implements IInvokeResponder
	{

		private var _defaultFaultListener:Function;

		private var resultListeners:Array ;

		private var faultListener:Array ;


		public function AbstractResponder(defaultFaultListener:Function = null)
		{
			_defaultFaultListener = defaultFaultListener;
		}

		public function addResultListener(handler:Function, ...args):IInvokeResponder
		{
			if(!resultListeners){
				resultListeners = new Array();
			}
			resultListeners.push(new Listener(handler,args));
			return this;
		}

		public function addFaultListener(handler:Function, ...args):IInvokeResponder
		{
			if(!faultListener){
				faultListener = new Array();
			}
			faultListener.push(new Listener(handler,args));
			return this;
		}


		protected function notifyResultListeners(result:Object,first:int=0):void{
			try{
				if(resultListeners){
					for(var i:int=first;i<resultListeners.length;i++){
						var listener:Listener = resultListeners[i];
						var func:Function = listener.handler;
						var params:Array = listener.argumenys;
						params.unshift(result);
						func.apply(null,params);
					}
				}
			}
			finally{
				if(_monitorToken){
					_monitorToken.stop();
				}
			}


		}


		protected function notifyFaultListeners(fault:Object,first:int=0):void{
			try{
				if(faultListener){
					for(var i:int = first;i<faultListener.length;i++){
						var listener:Listener = faultListener[i];
						var func:Function = listener.handler;
						var params:Array = listener.argumenys;
						params.unshift(fault);
						func.apply(null,params);
					}
				}else if(_defaultFaultListener!=null){
					_defaultFaultListener.apply(null,[fault]) ;
				}
			}finally{
				if(_monitorToken){
					_monitorToken.stop();
				}	
			}
		}

		protected function clear():void{
			resultListeners = [];
			faultListener = [];
		}

		private var _monitorToken:IMonitorToken ; 

		public function installMonitor(monitor:IProgressMonitor,parent:DisplayObject,cancelHandler:Function=null):IInvokeResponder{
			if(monitor){
				_monitorToken  = monitor.begin(this,parent,cancelHandler);
			}
			return this;
		}
	}
}

class Listener {

	private var _handler:Function;

	private var _args:Array ;

	public function Listener(handler:Function,args:Array){
		_handler=handler;		    
		_args=args;
	}

	public function get handler():Function{
		return _handler;
	}

	public function get argumenys():Array{
		return _args.concat();
	}

}
